package com.pkrete.xrd4j.rest.converter; import org.json.XML; import org.json.JSONArray; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class converts XML strings to JSON strings. If XML element names * start with '__at__' string, it's converted to '@' character that's used * in JSON-LD as the first character in keys. * * @author Petteri Kivimäki * @author Markus Törnqvist */ public class XMLToJSONConverter implements Converter { private static final String ARRAY = "array"; private static final Logger logger = LoggerFactory.getLogger(XMLToJSONConverter.class); /** * Converts the given XML string to JSON string. class. * * @param data XML string * @return JSON string or an empty string if the conversion fails */ @Override public String convert(String data) { logger.debug("CONVERTING " + data); try { JSONObject asJson = XML.toJSONObject(data); if (asJson.has(ARRAY)) { // If the JSON object has an "array" key, it's an array JSONArray jsonArray = asJson.getJSONArray(ARRAY); logger.debug("RETURN ARRAY " + jsonArray.toString()); return jsonArray.toString(); } else { // Did not have top-level array key. this.normalizeObject(asJson); String jsonStr = asJson.toString(); // JSON-LD uses '@' characters in keys and they're not allowed // in XML element names. Replace '__at__' with '@' in keys. jsonStr = jsonStr.replaceAll("\"__at__(.+?\"\\s*:)", "\"@$1"); logger.debug("NORMALIZED TO " + jsonStr); return jsonStr; } } catch (Exception e) { logger.error(e.getMessage(), e); logger.warn("Converting XML to JSON failed! An empty String is returned."); return ""; } } protected JSONObject normalizeObject(JSONObject obj) { logger.debug("NORM: " + obj.toString()); for (String key : JSONObject.getNames(obj)) { JSONObject subtree = obj.optJSONObject(key); if (subtree != null) { if (subtree.has(ARRAY)) { // Set the array as the direct value JSONArray subarray = subtree.getJSONArray(ARRAY); obj.put(key, subarray); logger.debug("recurse with {}: {}", key, subtree.toString()); } // See if there's more to do in this subtree normalizeObject(subtree); } } return obj; } }